package server;
import msgs.*;

import java.io.*;
import java.util.*;
/**
 * Authorizes PMs and handles offline pms
 * Team 9: Andrew Hayworth, Brian Parrella, Ryan Kortmann, Nina Papa
 * @author Andrew Hayworth
 */
public class PMHandler extends Thread implements TTConstants{
	private PMMsg pmmsg;
	
	public PMHandler(ClientMsg cmsg) {
		this.pmmsg = (PMMsg) cmsg;
	}
	
	public void run() {
		//ick, i dont like how i did this
		// essentially we see if they set an offline flag -- if they didn't we auth and send details back, if they did and the user
		// really is offline, then we go into offline pm
		// we handle the non-offline case first.
		System.out.println(pmmsg.isOffline());
		if (!(pmmsg.isOffline())) {
			// auth
			if (!(Arrays.equals(pmmsg.getClientKey(), TTServer.connTable.get(pmmsg.getName()).getClientKey()))) {
				// DENY!
				pmmsg.setSpecialResponse(1);
				ClientSender.outQ.add((ClientMsg) pmmsg);
				assert (pmmsg.getResponse() != null);
				return;
			}
			//System.out.println("Server thinks wants user is " + pmmsg.getWantsUser());
			//System.out.println("Server thinks name is " + pmmsg.getName());
			if ((TTServer.blockList.containsKey(pmmsg.getWantsUser()) && !(TTServer.blockList.get(pmmsg.getWantsUser()).contains(pmmsg.getName())))
					|| !(TTServer.blockList.containsKey(pmmsg.getWantsUser()))) {
				System.out.println("Keys are " +TTServer.connTable.keys());
				if (TTServer.connTable.containsKey(pmmsg.getWantsUser())) {
					// ok!
					System.out.println("User is online:");
					System.out.println(pmmsg.getWantsUser());
					pmmsg.setSpecialResponse(0);
					assert (pmmsg.getResponse() != null);
					pmmsg.setUserIP(TTServer.connTable.get(pmmsg.getWantsUser()).getIp());
				}
				else {
					// offline pm!
					pmmsg.setSpecialResponse(2);
					assert (pmmsg.getResponse() != null);
					ClientSender.outQ.add((ClientMsg) pmmsg);
				}
			}
			ClientSender.outQ.add((ClientMsg) pmmsg);
			return;
		}
		else {
			// oh god, they want to offline pm.
			// ensure they're REALLY offline, and if they are, return it back to the user with "NO_THEY_ARE_ONLINE"
			if (!(TTServer.connTable.containsKey(pmmsg.getWantsUser()))) {
				// k cool theyre offline
				// add msg to queue, if they're in there, else make a queue for them.
				
				// so, this is the block if they already have some kind of offline queue going
				if (TTServer.offlinePm.containsKey(pmmsg.getWantsUser())) {
					
					// this is if they have a block, and this user has already tried to offline them before
					if (TTServer.offlinePm.get(pmmsg.getWantsUser()).containsKey(pmmsg.getName())) {
						synchronized(TTConstants.lock) {
							TTServer.offlinePm.get(pmmsg.getWantsUser()).get(pmmsg.getName()).add(pmmsg.getMsg());
							TTServer.writeHash(new File("data/offlinePm.dat"), TTServer.offlinePm);
						}
					}
					// and this is if they have a block, but this specific user hasn't tried an offline pm
					else {
						synchronized(TTConstants.lock) {
							//Hashtable<String, ArrayList<String>> ht = new Hashtable<String, ArrayList<String>>();
							ArrayList<String> al = new ArrayList();
							al.add(pmmsg.getMsg());
							//ht.add(pmmsg.getName(), al);
							TTServer.offlinePm.get(pmmsg.getWantsUser()).put(pmmsg.getName(), al);
							TTServer.writeHash(new File("data/offlinePm.dat"), TTServer.offlinePm);
						}
					}
				} 
				
				// and here is where we get if they have no block at all.
				else {
					synchronized(TTConstants.lock) {
						ArrayList<String> al = new ArrayList<String>();
						al.add(pmmsg.getMsg());
						Hashtable<String, ArrayList<String>> ht = new Hashtable<String, ArrayList<String>>();
						ht.put(pmmsg.getName(), al);
						TTServer.offlinePm.put(pmmsg.getWantsUser(), ht);
						TTServer.writeHash(new File("data/offlinePm.dat"), TTServer.offlinePm);
					}
				}
				pmmsg.setResponse(Responses.OK);
			}
			else {
				// they're back online, let the remote user know
				pmmsg.setSpecialResponse(3);
				pmmsg.setUserIP(TTServer.connTable.get(pmmsg.getWantsUser()).getIp());
			}
			ClientSender.outQ.add((ClientMsg) pmmsg);
		}
	}
}
